OutpostUniverse / OP2Archive

Console Application for examining, creating, and extracting files from Outpost 2 .vol and .clm archives.
https://wiki.outpost2.net/doku.php?id=outpost_2:helper_programs:op2archive
MIT License
1 stars 0 forks source link

Inject version info from CMake into platform specific projects #23

Closed Brett208 closed 5 years ago

Brett208 commented 6 years ago

When this gets merged into the master branch, the Visual Studio Project will no longer work. We could continue working this branch to develop the packing script with CMake before merging if we want to wait a while longer before deleting the platform specific project files from the repository.

DanRStevens commented 6 years ago

From what I understand of this, the version string is now manually updated in CMakeLists.txt, rather than in Main.cpp. I suppose this is to demo how CMake can feed the values to generated source files.

What is the main problem with the Visual Studio project file after introducing this? I'm not sure I quite know how to describe it clearly. It seems inconvenient in that the generated file needs to be added to the project to be compiled, and that it won't auto updated without re-running CMake. Is there more?

Brett208 commented 6 years ago

What I mean about Visual Studio is that you would no longer be able to use the non-CMake generated Visual Studio project after inclusion of this branch. You would have to manually create Version.cpp for it. The CMake generated Visual Studio version still works fine without tweaking after generating it.

This will also break the non CMake generated Makefile as well. I don't know if there is built in functionality to do something like this using a Makefile.

Yes, using this setup, you would need to rerun the generate command to pull in the new version number. Just like you would rerun CMake when a source file is added or other CMake updates are made.

Brett208 commented 6 years ago

It occurred to me that if we include version information in a similar manner in OP2Utility, there will be name collisions with the namespace VersionInfo. Instead if we use OP2ArchiveVersion and OP2UtilityVersion for the namespaces, you could do interesting things like reference the library utility version number in the OP2Archive help script, in addition to the obvious need of avoiding the namespace collision.

DanRStevens commented 6 years ago

Is Version.cpp created when CMake runs to produce the Makefile/VS project file, or does it create Version.cpp during the build?

Currently, I sort of feel this solution is incomplete if the version number must be manually set in CMakeLists.txt. It would be desirable to have a single source of truth for the version number. I think that is best done with version control tags. Perhaps you see differently though.

Good point about keeping library and executable version numbers different. Might even make sense for some help or about text to list both version numbers. Though it's probably more relevant for dynamic linking than static linking. With static linking, if you recompile the front end to use a new backend, you'd change the version number of the front end.

DanRStevens commented 6 years ago

Just a quick thought here, but should the version info be embedded in a project or library specific namespace, as in OP2Utility::Version:: or OP2Archive::Version::, rather than OP2ArchiveVersion? If the project already introduces a top level namespace, we should probably strive to put everything under that one name, rather than introduce a bunch of similar names.

Brett208 commented 6 years ago

Version.cpp will be created when you generate the platform specific build tools. So it will exist before attempting to compile the source code itself.

Agreed code in this branch will need extended to be useful. Just had to start somewhere. I have no problem trying to pull in version info from Git. Once it is written we should play with it a bit to make sure things work well though.

A top level namespace for a project is fine with me. More important for OP2Utility than OP2Archive though since it is a library project. I'm happy leaving this as is and then upating as suggested when a top level namespace is implemented.

Brett

Brett208 commented 6 years ago

With this new commit, you can now run the console command CPack within the CMake generated binary directory.

It will produce the directory ./_CPack_Packages/win32/ZIP/. This directory will include a subdirectory called OP2Archive-1.2.0-win32 containing the following files:

A zip file is also created in ZIP directory with the same name as the subdirectory including all the files.

I'm not seeing a way to create a second directory/ZIP file that contains only the PDB file. It may be best to remove fetching the PDB automatically with CPack and just manually copy/zip it after running CPack.

I haven't figured out a proper way to handle packaging both an x86 and x64 version of OP2Archive on MSVC yet.

This is sort of rough because I'm not sure what the best practice is yet.

-Brett

DanRStevens commented 6 years ago

Looks like good progress.


What if Version.cpp was pre-existing, would it be overwritten? I'm wondering if it makes sense to include a Version.cpp with dummy version values, such as 0.0.0.

Related to the above, do we care to support users who don't have CMake installed? It might make sense to include the Visual Studio project files pre-generated in a source distribution. That may or may not entail having Visual Studio project files checked in to version control.


Is there much difference between the existing Visual Studio project file, and the one generated by CMake? I suppose if CMake can generate the one that currently exists, or something very close to it, that helps the case for removing the current project file.

As it stands now, it feels like we would be losing something by moving over completely, though it's not clear what the difference is. I assume the differences are mostly in the post build steps.


It would be desirable to strip the .PDB for distribution to the end user. It's quite large, and the end user doesn't need it.

I'm not certain how CMake would handle generating multiple post-build packages. Sounds like you'd want to set multiple archive build targets, or perhaps make use of multi-stage build capabilities. Alternatively, I've seen CI systems have a way to save certain build artifacts. Sometimes that includes things like log files, though it may be appropriate for saving things like PDB files. They're not exactly the target output, but rather produced as a side effect of building the main target. Maybe AppVeyor can archive these when it produces the test builds, or at least archive them if it's a tagged test build.


For x86 and x64 packages, I think there is a way to build executables that can run in either mode. They're larger though, since they contain the code for both build types. Not sure we want to go there though.

Some CI/CD pipelines support the concept of fan-in and fan-out. That might allow collecting artifacts from multiple builds, and producing a package from that. Some can potentially do this with results from multiple systems spanning multiple OSes. I'd be happy though with one archive per platform, which I think would be easier.


How is the current build produced on Windows? I'm assuming you choose a configuration for the project in Visual Studio, then run a build, and have the post-build scripts package things up. I guess I had assumed CMake generated a Visual Studio project file, and then the build proceeded as before from within Visual Studio. Sounds like the post-build stuff is changing a bit when using CMake. Does CMake run MSBuild on its own, or use NMake? The CPack stuff sounds like the build is happening entirely different, and outside of Visual Studio.

DanRStevens commented 6 years ago

This might be helpful: AppVeyor: Packaging Artifacts

AppVeyor is already making test builds of all the commits. Would make sense to have AppVeyor zip up the results into a package for deployment, particularly if the build corresponds to a git tag commit, which would correspond with release packages.

Brett208 commented 6 years ago

I like the idea of including a default/dummy Version.cpp to ease first time compilation for non CMake users. This idea conflicts a little with the current setup though. Since Version.cpp is a generated file, it should be produced in the binary build directory generated by CMake, not in the source code directory.

Once the code was generated by CMake, you would get constant messages requesting to overwrite Version.cpp since it would not longer be the default value. Maybe there is an elegant way around this though?


CMake generates a Visual Studio solution that is structured significantly differently than the Visual Studio solution I 'hand-crafted'. For one thing, it includes 2 extra projects called ALL_BUILD and ZERO_CHECK. Additionally when adding CPack to the CMake file, 2 more projects are included called INSTALL and PACKAGE. These projects are in addition to the OP2Archive and OP2Utility projects. The 4 additional projects contain no source code files, just a single .rule file each. Except for ALL_BUILD which contains CMakeLists.txt.

I'm not really familiar with makefiles, but I get the impression CMake lines up fairly closely with a Makefile and probably produces a decent Makefile. I think a Visual Studio user sacrifices some cleanliness in their solution to use CMake.

By default, CMake generates a Visual Studio project that only has a WIN32 configuration. I haven't found any documentation stating how to have CMake generate a project with both x86 ad x64 configurations as one would have default in Visual Studio.

I think the correct answer according to CMake, would be to generate 2 separate Visual Studio projects in separate directories. So I could generate a VisualStudioX86 and VisualStudioX64 in separate directories and just switch back and forth as needed. While switching between the projects would be annoying since Visual Studio has a built in way to prevent this, since the 2 projects would share the same source code, it wouldn't be that big of a deal.


I want to research telling CPack to use an x64 MSVC generator and see how feasible that is. It may be as simple as telling CPack to generate twice, once for x86 and once for x64. But like you mentioned, CMake documentation is poor, and CPack is even worse.

CMake can compile using MSVC from the command line. I'm not savvy enough to know whether it is using nmake to do that or not, although this is an area I wanted to look into soon for use with CPack. I would be fine using the command line to produce the final executables for release. I would compile first in Visual Studio to work on the code and fix bugs and then just compile on the command line for release.


It looks like AppVeyor would be capable of preparing what I currently want in a release package. I suspect that CPack is capable of a lot more complex actions like preparing an installer that maybe AppVeyor could not accomplish if we want to move that way in the long run. I don't really have enough experience with either to make an educated decision one way or the other.

-Brett

DanRStevens commented 5 years ago

Perhaps we should consider closing this once the other version information branch is merged in.

Brett208 commented 5 years ago

Yeah, long live CMake in OP2 code...

DanRStevens commented 5 years ago

Should we remove the branch? Or did you want to salvage something from it first?

Brett208 commented 5 years ago

Might be worth saving for now.