{"id":48730,"date":"2019-12-12T06:00:46","date_gmt":"2019-12-12T11:00:46","guid":{"rendered":"https:\/\/www.shamusyoung.com\/twentysidedtale\/?p=48730"},"modified":"2019-12-13T09:10:34","modified_gmt":"2019-12-13T14:10:34","slug":"jai-part-13-project-files","status":"publish","type":"post","link":"https:\/\/www.shamusyoung.com\/twentysidedtale\/?p=48730","title":{"rendered":"Programming Vexations Part 13: Project Files"},"content":{"rendered":"<p>Here we are at the end of this series. I was hoping we&#8217;d get a public beta of JAI before the end of the year and I could end this by experimenting with a new language, but it looks like that didn&#8217;t pan out.<\/p>\n<p>This last vexation isn&#8217;t remotely the most serious problem, but it&#8217;s the one that annoys me the most<span class='snote' title='1'>Or maybe it&#8217;s second, after header files.<\/span>.<\/p>\n<p>Of all the things that suck the joy out of writing code, I think that managing project files is pretty high on the list. This is sort of linked to the problem where <a href=\"?p=9557\">integrating libraries in C++ is a madhouse and a chore<\/a>. If using someone else&#8217;s code was easier, then the headaches of setting up project files would be less of an issue. But these two problems exacerbate each other and force you to spend time putting all the files in the right places and referring to them in the right order.<\/p>\n<p><!--more--><br \/>\nDisclaimer: This is one of those rare instances where Linux seems to be more user-friendly and turnkey than Windows<span class='snote' title='2'>Despite the efforts of Microsoft to &#8220;idiot-proof&#8221; their OS, there are surprisingly a lot of these.<\/span>. It&#8217;s been years since I did any programming on Linux, but I remember using a package manager that could find the required files, download them, and put them in the right place. There seem to be some basic rules about how to share source files. On Windows, this entire process is done manually and there doesn&#8217;t seem to be a coherent set of rules. Every Windows-based library has its own logic regarding how the files should be structured on your hard drive and how they should be added to your project.<\/p>\n<p>In any case, this means there&#8217;s an annoying amount of sorting and accounting the programmer has to do in order to get everything working right, all of which is complicated by the archaic C system of header files. It&#8217;s not that these problems are too difficult. If you can write code to do memory management then these tasks shouldn&#8217;t be challenging for you. The problem is that these sorts of busywork tasks are something that &#8211; in a sane world &#8211; would be offloaded to the computer. (Assuming they needed to be done at all.) Computers are very good at large-scale sorting problems, and our programmer has way more important stuff they could be thinking about.<\/p>\n<h3>Vexation #7: Fiddling With Project Files is Not Programming<\/h3>\n<p>You need some way to tell the compiler (or your development tools) what files are part of your project. C compilers are terminal programs<span class='snote' title='3'>This just means that they run in a text-based context like a DOS window.<\/span> and they don&#8217;t automatically know what files they need to be compiling or where to find the various libraries you&#8217;re using.\u00a0 There are a lot of options for compiling. Is this the debug version? What character set are we using? What libraries do we need to pull in? Is this 32 or 64 bit? What sorts of optimizations should the compiler apply to your code?<\/p>\n<p>In the old days the programmer would have to type a bunch of inscrutable crap into the terminal window. For example, this is what you&#8217;d have to type into DOS to compile a modern program:<\/p>\n<p><tt>D:\\Projects\\Source\\BugHunt\\Debug\\BugHunt.exe\" \/MANIFEST \/NXCOMPAT \/PDB:\"D:\\Projects\\Source\\BugHunt\\Debug\\BugHunt.pdb\" \/DYNAMICBASE \"kernel32.lib\" \"user32.lib\" \"gdi32.lib\" \"winspool.lib\" \"comdlg32.lib\" \"advapi32.lib\" \"shell32.lib\" \"ole32.lib\" \"oleaut32.lib\" \"uuid.lib\" \"odbc32.lib\" \"odbccp32.lib\" \/DEBUG \/MACHINE:X86 \/INCREMENTAL \/PGD:\"D:\\Projects\\Source\\BugHunt\\Debug\\BugHunt.pgd\" \/SUBSYSTEM:WINDOWS \/MANIFESTUAC:\"level='asInvoker' uiAccess='false'\" \/ManifestFile:\"Debug\\BugHunt.exe.intermediate.manifest\" \/ERRORREPORT:PROMPT \/NOLOGO \/LIBPATH:\"E:\\SDK\\boost_1_55_0\\stage\\lib\" \/LIBPATH:\"F:\\SDK\\gl\\lib\\\" \/TLBID:1<\/tt><\/p>\n<p>Nobody actually <b>does<\/b> this, of course. The <a href=\"?p=48221\">IDE<\/a> handles it for us. I&#8217;m just trying to show that behind that sleek interface is an architecture that dates back to the 1970s.<\/p>\n<p>Very few programmers pay attention to this stuff. We set all the compile options using a friendly interface and let the development environment figure out what esoteric options are needed to get the compiler to do what we want.<\/p>\n<p>If you&#8217;re programming on Windows then you&#8217;re probably using Visual Studio and you&#8217;ll do things one way, but if you&#8217;re on Linux you&#8217;ll do things a different way. The language is supposedly platform-independent, but the system that holds the project together isn&#8217;t. Like header files, this is understandable due to the age of the language. It&#8217;s not that the language was designed poorly, it&#8217;s just that it was designed a very long time ago for machines that are very different from what we use today.<\/p>\n<p>So we have our C++ code, then we have some project file that&#8217;s not part of the C++ language but is needed so the editor knows what files we want to compile, and we&#8217;ve got these huge command-line arguments that nobody understands<span class='snote' title='4'>Statistically speaking, anyway.<\/span>. Which means that your project requires 3 different sets of information in 3 different formats:<\/p>\n<ol>\n<li>The source code itself, which consists of source files and header files.<\/li>\n<li>Some sort of file explaining what source files are part of the project and where they can be found.<\/li>\n<li>The compile options to tell the compiler how to behave.<\/li>\n<\/ol>\n<p>If you&#8217;re using Visual Studio, then the last two items are stored in the proprietary project file. Just to keep things interesting, Microsoft likes to fiddle with the format of the project files from one version to the next, creating a one-way conversion to the latest edition of Visual Studio. Which means that if one person upgrades, everyone on the project needs to upgrade. This also means its a pain in the ass for other projects &#8211; like Linux programmers &#8211; to make use of this file. This should all sound familiar to people who remember Microsoft Word and its ever-changing .docx format.<\/p>\n<p>For years the structure of Visual Studio projects was basically folk knowledge. There wasn&#8217;t any official documentation. It wasn&#8217;t something you could learn in college. It was this whole body of specialized knowledge that you were just expected to know somehow. If you had a problem communicating with the compiler, you had to post on a forum somewhere and hope someone else out there had already fallen into this trap, found their way out, and posted their escape route to the internet. In the early aughts, I lost a lot of time to weird little mysteries when trying to do special builds or deal with oddly structured libraries. I don&#8217;t run into those problems anymore, but I don&#8217;t know if it&#8217;s because Visual Studio got better or because my work is simpler.<\/p>\n<p>In any case, the answer seems obvious: Don&#8217;t use Microsoft&#8217;s tools. That should keep you out of trouble, right?<\/p>\n<p>However, the tools are otherwise really good. They&#8217;re also very common in the games industry where so much of the development process takes place on Windows machines. Based on the GDC talks I&#8217;ve watched, Visual Studio seems to be pretty standard in AAA development.<\/p>\n<p>None of this is the fault of the language, of course. But it&#8217;s still a dumb headache that developers have to deal with. It might even be a contributing factor to why Linux gaming is still in such sad shape. Moving your project off of Visual Studio and getting it to compile on Linux has got to be a huge pain in the ass.<\/p>\n<h3>We Can Do Better. I Think.<\/h3>\n<p>As I&#8217;ve said before, my experience with modern languages is pretty limited. Still, every language I&#8217;ve tried has been better than the C family when it comes to project files.<\/p>\n<p>Like I keep saying, I don&#8217;t want this series to sound like a commercial for Jai. The language isn&#8217;t out yet, it&#8217;s all unproven, I haven&#8217;t used it, etc etc. Having said that, I really like the way Jai supposedly handles project files. In Jai, all three kinds of data &#8211; source code, compile options, and included files &#8211; are expressed in the same file. Essentially, your source code <b>is<\/b> the project file, and the compile options are specified in your code. You communicate with the compiler using the same language you&#8217;re writing the program in.<\/p>\n<p>You invoke the compiler by pointing it at a single file. Something like this:<\/p>\n<p>jai main.jai<\/p>\n<p>This calls the compiler and tells it to compile the file main.jai. That file will tell the compiler what other files are part of the project, where they are, and what compile options we want to use. The compiler will then process all of the files in one go, building up a complete understanding of all the functions. You don&#8217;t need to make header files to tell it how to find things, because it can just figure it out on its own.<\/p>\n<p>This means that compiling the program will be exactly the same on Windows, Linux, Mac, or wherever else you&#8217;re trying to work.<\/p>\n<p>I love this idea so much. Your project structure isn&#8217;t hidden in a bunch of specialized files that are tied to your development environment. They&#8217;re something the programmer can read and understand. <\/p>\n<p>This is the kind of convenience that you usually only get in higher-level languages. The assumption is usually that if you want an easy compile, then you must also want garbage collection, copious error checking, and lots of other convenience features that hinder your ability to write really fast code. If you want direct memory management and freewheeling data access, then you must also want a really fiddly and obtuse system for compiling it.<\/p>\n<p>Along those lines, Jai offers another feature that&#8217;s usually associated with higher-level languages&#8230;<\/p>\n<h3>Introspection<\/h3>\n<p>Introspection is a pretty strange concept, but it involves a program being aware of the code used to generate it. Let&#8217;s return to our old friend the space marine:<\/p>\n<pre lang=\"cpp\">class SpaceMarine\r\n{\r\n  bool dead;\r\n  char[8] name;\r\n  Vector3 position;\r\n  float stubble;\r\n  short bullets;\r\n  short kills;\r\n  int dead_wives;\r\n  int hitpoints; \/\/Don't forget the hitpoints this time, Shamus\r\n  bool cigar;\r\n  int mana; \/\/I really think the designers need to get on the same page here.\r\n};<\/pre>\n<p>That&#8217;s the class definition. That block of code describes a SpaceMarine, what its fields are called, and what kinds of data they store. If you want to use a SpaceMarine and maybe give him some bullets, you would create an instance of it in code like so:<\/p>\n<pre lang=\"cpp\">\r\n\/\/Please don't give me a hard time about encapsulation. I'm trying to illustrate something here.\r\n\/\/I'm not going to ship this code, I promise.\r\nSpaceMarine shepard;\r\nshepard.bullets = 10;\r\n<\/pre>\n<p>When we&#8217;re looking at the code we can clearly see the name of the class (SpaceMarine) and the name of the variable (shepard) and we can see what all the internal parts of a SpaceMarine are called. The important thing to remember is that the compiler can see this, but not the compiled program.<\/p>\n<p>Remember that once a program is compiled, it gets turned into stuff like this:<\/p>\n<pre lang=\"asm\">\r\nmov eax,4\r\nmov ebx,1\r\nint 80h\r\n\r\nmov eax,1\r\nmov ebx,0\r\nint 80h\r\n<\/pre>\n<p>The various commands boil down to mechanical instructions like &#8220;Move program execution to this instruction. Now copy stuff from this memory address to that other one. Now take the value in this address, add some number onto it, and copy it back to the first location. Now move execution to this other memory address and do whatever instructions are stored there.&#8221; It&#8217;s all numbers. There&#8217;s no way for the program to know that the stuff stored in memory address 1D4573 was originally a variable called &#8220;shepard&#8221;. All of those handy human-readable names are lost\u00a0 when the program is compiled.<\/p>\n<p>But!<\/p>\n<p>It <b>is<\/b> possible to retain that information. Doing things this way costs extra memory and processor cycles, so not all languages support it. This sort of thing is called introspection.<\/p>\n<p>Actually, sometimes it&#8217;s called <b>reflection<\/b>.<\/p>\n<p>Actually, sometimes it&#8217;s called <a href=\"https:\/\/en.wikipedia.org\/wiki\/Run-time_type_information\">RTTI<\/a> for &#8220;Run Time Type Information&#8221;, but only in C++<span class='snote' title='5'>C++ author Bjarne Stroustrup did not include run-time type information in the original version of his language, because he thought this mechanism was often misused. This is a really strange reason, given how the rest of C++ lacks anything in the realm of safety features. Like, he was willing to include buzzsaws in his language in the form of memory pointers, but he thought the paring knife of RTTI was too risky? I don&#8217;t know. He&#8217;s the author of one of the most successful languages on the planet and all I&#8217;ve made is this silly blog, but it sounds funny to me.<\/span>. Sort of. RTTI isn&#8217;t really the same thing, but it is related. It&#8217;s complicated.<\/p>\n<p>I&#8217;m not going to try and untangle these terms, since people seem to disagree on their frequently-overlapping definitions. For now let&#8217;s just stick to talking about introspection and ignore the other two terms. We can poke our head into that wasp nest someday in the future if we&#8217;re feeling brave and there&#8217;s something to be gained in the effort.<\/p>\n<p>I never have a use for introspection when making production code, but I&#8217;ve found it immensely useful for debugging tools and meta-analysis. The classic command console in the old Quake and Half-Life games is a great example of using introspection. The user can type in text, and the program can use that text to manipulate or display variables while the program is running.<\/p>\n<p>There are many other uses for introspection, but they don&#8217;t usually crop up on my projects.<\/p>\n<p>At any rate, introspection is generally associated with higher level languages like C# and Java. C++ doesn&#8217;t do introspection at all. Neither does Rust. D language seems to partly support it, but I think I&#8217;d need to know the language myself to <a href=\"https:\/\/forum.dlang.org\/thread\/pf8nh2$27np$1@digitalmars.com\">follow the conversation<\/a>.<\/p>\n<p>Jai supposedly has introspection, and apparently it&#8217;s even seen as <a href=\"https:\/\/github.com\/BSVino\/JaiPrimer\/blob\/master\/JaiPrimer.md\">one of the main pillars of the language<\/a>. It&#8217;s interesting to see so many high-level programming ideas being put into an ostensibly low-level language. Jai is making some very revolutionary promises. I don&#8217;t have the expertise to predict anything, but I am <b>extremely eager<\/b> to see how it all turns out.<\/p>\n<h3>Wrapping Up<\/h3>\n<p>I finished writing this series in late summer. At the time, I was really hoping I could end this series &#8211; or begin a new one &#8211; with some actual coding in JAI and see how true \/ ridiculous \/ misguided \/ prescient my various claims were. But it didn&#8217;t work out that way. Drat the luck.<\/p>\n<p>I have no idea if Jai will be any good, but I really am on board with the idea that a programming language designed for games could be immensely helpful. I realize we&#8217;d still be left with the chicken\/egg problem and I don&#8217;t know how you overcome that. A New Thing needs to be a lot better than the Old Thing to overcome the cost of switching. Are the gains big enough to break through the C++ hegemony? I don&#8217;t know. It certainly wouldn&#8217;t happen overnight. It would probably start with indies, and expand to larger and larger projects. <\/p>\n<p>Or maybe we&#8217;re doomed to use the clunky and vexing C++ to make our AAA games for another 40 years. <\/p>\n<p>I guess we&#8217;ll see. Thanks for reading.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Here we are at the end of this series. I was hoping we&#8217;d get a public beta of JAI before the end of the year and I could end this by experimenting with a new language, but it looks like that didn&#8217;t pan out. This last vexation isn&#8217;t remotely the most serious problem, but it&#8217;s [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[66],"tags":[],"class_list":["post-48730","post","type-post","status-publish","format-standard","hentry","category-programming"],"_links":{"self":[{"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/posts\/48730","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=48730"}],"version-history":[{"count":12,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/posts\/48730\/revisions"}],"predecessor-version":[{"id":48742,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/posts\/48730\/revisions\/48742"}],"wp:attachment":[{"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=48730"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=48730"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=48730"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}