I am creating a library of script methods and only want to include them when needed in my installers.
Some of the methods need to use other methods so I was putting the #include "filename.iss" for the needed methods in the file with the method that needs it.
However, if I include two files in an installer script file that also include a common file I get a "Duplicate identifier" error in the second file that includes it.
I've searched for something like #include-once but can't find any results for it.
To reproduce you can just include the same file twice:
#include "AddReplaceLinesInFile.iss"
#include "AddReplaceLinesInFile.iss"
The only way I can see to avoid this is to not put the includes in the files with the methods that need them and just add them in the main installer script.
I'm leaving the includes in the top of the method files that need them but commenting them out - for documentation purposes and to make it easy to copy and paste them into my main installer script. However I'd prefer to use something like an include-once capability.
Does Inno Setup have anything like include-once or a way to test for an already defined method so I could create something similar?
TIA
Use the same trick as is used in C/C++, the include guard:
In the C and C++ programming languages, an #include guard, sometimes called a macro guard, is a particular construct used to avoid the problem of double inclusion when dealing with the include directive.
Surround the code in the included file with #ifndef UniqueName, #define UniqueName ... #endif:
#ifndef IncludeIss
#define IncludeIss
procedure Test;
begin
end;
#endif
The UniqueName is typically the same as filename, with punctuation removed (to make it a valid identifier). I.e. for include.iss the name can be IncludeIss.
See Inno Setup Preprocessor: #ifdef, #ifndef, #ifexist, #ifnexist.
There is no such thing as include-once.
Inno Setup is Pascal based where functions (and procedures) are global! There are no private ones.
Preprocessor Symbols are scoped to the .iss file and to make them global use public keyword.
Variables have really unpleasant behavior: if you define global variable (in [Code] section) with the same name as local variable you never know into which variable the value is really assigned.
Compiler does not check this which is really bad.
Related
A particular C++ logging library called spdlog that I use in my project has a broken package on CentOS (the platform I'm trying to compile on) where the header file will only compile if SPDLOG_FMT_EXTERNAL is defined before any of its files are included. [And this will not be fixed.]
I am trying to find a way to use autoconf directives to test for the presence of this header file - previously I used a homegrown macro that compiles a program which uses that, but its speed latency is unacceptably slow so I am trying to replace it.
Here is the relevant snippet of my configure.ac:
dnl check for libfmt is done earlier...
AC_CHECK_HEADERS([spdlog/spdlog.h], [have_spdlog="yes"], [have_spdlog="no"])
if test x$have_spdlog = xyes; then
LDFLAGS="$LDFLAGS -lspdlog -lfmt";
else
AC_MSG_ERROR([spdlog is required for logging support but is missing.])
fi
The header file spdlog/spdlog.h exists, but Autoconf deems it as not usable because it won't compile by itself.
AC_CHECK_HEADERS has a parameter I can specify include files required to include that particular header file. I can use that to specify the #define macro before the file is included.
Is there an easier way to just directly specify a macro without creating a new header file?
After some experimenting, I learned that the fourth parameter to AC_CHECK_HEADERS accepts macros as well - anything that can be used in a C/C++ preprocessor works as well, such as #ifdef, #endif and so on. It is not restricted to only #include directives.
AC_CHECK_HEADERS([spdlog/spdlog.h], [have_spdlog="yes"], [have_spdlog="no"], [
#define SPDLOG_FMT_EXTERNAL
])
Ok I know you can do this in Inno Setup:
#define AppVer "0.0.11"
Then use it like
[Setup]
AppVerName={#AppVer}
Now imagine I have a file named VERSION whose contents are "0.0.11".
Is there a way the contents of the file VERSION into the Inno Setup preprocessor variable somehow?
Using ISPP's GetFileVersion function is the preferred method (since your installer version should match your application's version, after all). So if this is what you actually wanted to do, you should accept jachguate's answer.
In case you really do want to read the version from a text file instead of from the executable file, then there are two possibilities:
The first: If you can modify the internal format of the file, then you can simplify things considerably by making it look like an INI file:
[Version]
Ver=0.0.11
Given this, you can use ISPP's ReadIni function to retrieve the version:
#define AppVer ReadIni("ver.ini", "Version", "Ver", "unknown")
The second alternative, if you can't change the file format, is to use the FileOpen, FileRead, and FileClose ISPP functions, eg:
#define VerFile FileOpen("ver.txt")
#define AppVer FileRead(VerFile)
#expr FileClose(VerFile)
#undef VerFile
I repeat, though: it's better to get the app version from the executable file itself instead. This helps to ensure that everything matches up, for one thing.
You can use the Inno Setup Pre Proccessor (ISPP) GetFileVersion function to get the version directly from your executable file, like this:
[Setup]
#define AppVersion GetFileVersion("MyFile.exe")
#define AppName "My App name"
AppName={#AppName}
AppVerName={#AppName} {#AppVersion}
VersionInfoVersion={#AppVersion}
; etc
If you're using defines, you're already using ISPP.
In the event you want to do this at the installer's run time (#jachguate's answer covers the other possibility, and is probably the one you're looking for - I'll leave this in case it helps others at some point), you can use it's Pascal Script to do so. Something like this should work:
[Setup]
AppVer={code:MyVersion}
[Files]
// Other files
Source: "YourVersionFile.txt"; DestDir: "{app}"
[Code]
function MyVersion(Param: String): String;
var
VersionValue: string;
VersionFile: string;
begin
// Default to some predefined value.
Result := '0.0.0';
VersionFile := '{app}\YourVersionFile.txt';
if LoadStringFromFile(VersionFile, VersionValue) then
Result := VersionValue;
end;
See the help file topic "Pascal Scripting" for more information, including a list of the supported built-in functions.
From: http://www.jrsoftware.org/ishelp/
A C-like #include directive is supported, which pulls in lines from a separate file into the script at the position of the #include directive. The syntax is:
#include "filename.txt"
If the filename is not fully qualified, the compiler will look for it in the same directory as the file containing the #include directive. The filename may be prefixed by compiler:, in which case it looks for the file in the Compiler directory.
I need to branch a certain statement in a precompiled-header .h file, based on whether the .h is now being used to create the PCH (i.e., included in a cpp compiled with /Yc), or now included just to use the PCH (i.e., included in a cpp compiled with /Yu).
In other words, I'm looking for something like -
#ifdef NOW_CREATING_THE_PCH
#import yadayada_with_option_a
#else
#import yadayada_with_option_b
#endif
...and can't find anything.
Any ideas would be appreciated!
Thanks,
-Ofek
[Edit:] The reason I need this is that I use Incredibuild, and have started getting this warning. Per the FAQ suggestion, I wish to #import with no_implementation during PCH creation, and with implementation_only during PCH usage.
You can specifically change the configuration (in Visual Studio) of stdafx.cpp (or whatever source file you have that gets compiled with /Yc) to define the symbol NOW_CREATING_THE_PCH, leaving the symbol undefined for the rest of the source files (which get compiled with /Yu).
That's not something you get out-of-the-box, but if you need to do it just for one project (or a few), it's not a problem.
While this is not a direct answer to your question, the simplest way of solving this problem is to use the #import statement with no_implementation in the header file which is used to generate the precompiled header (usually StdAfx.h) and re-#import the header file into the source file that is used to trigger the generation of the pch with the parameter implementation_only. That way the implementation of the wrapper functions are being defined, but only in one place.
Suppose I have two vc++ project, proj_a and proj_b
proj_a contains a header file a.h
proj_b has dependency on proj_a. It contains file b.h that does #include <a.h>. I add a.h's directory in the "additional include directories" in its project settings to build it.
Now say, I have 100 more projects, whose files #include <b.h>. Only adding b.h's directory in the "additional" column does not work. I have to include the path of a.h too.. How to avoid this?
Simply put, how to keep the number of include paths for any vc++ project equal to the number of direct dependencies?
I don't have the option to set vc++ environment settings to globally include a.h's path since everybody else in my team will have to import my settings and things will turn messier..
I don't have enough idea but is there a way to achieve this through precompiled headers? I think they are project-specific and should not be shared across projects?
Dependencies are transitive. That is, since b.h includes a.h, anything that includes b.h will need to be able to find a.h. The only thing you can do about it is to somehow remove the dependency of b.h on a.h, perhaps by using a forward declaration for the types in a.h instead of relying on the full definition of the types from the header file.
If that's not an option, at least you can ease the pain of include paths that are duplicated across projects by using Visual C++'s "property sheet" feature. These let you define shared build settings in a single file which can be inherited by an arbitrary number of projects. This will also solve the problem of sharing these settings with your collaborators.
Thanks for the answer Nick. I could have used relative path to a.h inside b.h and save having additional-include-directories inside proj_b and rest of 100 projects.
Actually, in my case there are multiple flavors of proj_a: 'proj_a1, proj_a2, etc. each having a separate a.h. The other 100 projects decide on which flavor to include by having appropriate additional-include-directory in their settings. This was an issue, whenever we need to upgrade proj_a flavors, all include-dirs will need to be changed.
I got across this problem by removing all include-dirs and instead defining PROJ_A1, PROJ_A2, etc. in the rest of projects. b.h does not #include a.h anymore, it include a a_redirector.h header file instead (with relative path). Inside a_redirector.h, we have all #ifdef PROJ_A1, #ifdef PROJ_A2, etc. that looks at the include a particular a.h file (relative paths here too) depending on what has been defined.
Now, whenever we need to upgrade proj_a flavors, I need only to modify a_redirector.h only to point to all new a.h thereby having a single point of control as compared to the earlier architecture.
Is it possible to build resources into a static library and reuse them by simply linking with the library?
I'm primarily thinking about the case where you call a function in the library which in turn accesses resources.
The only thing you need to do to use resources (images, dialogs, etc...) in a static library in Visual C++ (2008), is include the static library's associated .res file in your project. This can be done at "Project settings/Linker/Input/Additional dependencies".
With this solution, the resources of the static library are packed into the .exe, so you don't need an extra DLL. Regrettably, Visual Studio does not include the .res file automatically as it does for the .lib file (when using the "project dependencies"-feature), but I think this small extra step is acceptable.
I have looked for a very long time for this solution, and now it surprises me it is that simple. The only problem is that it is totally undocumented.
It can be done, but it's quite painful: You can't do it by simply linking with the static library.
Consider this: resources are embedded in an EXE or DLL. When some code in the static library calls (e.g.) LoadIcon, it'll get the resources from the EXE or DLL that it's linked with.
So, if your static library requires resources to be available, you've got a couple of options:
You can have the library build them on the fly, and then use (e.g.) CreateDialogIndirect. See Raymond Chen's "Building a dialog template at run-time".
You can have them embedded in the library as simple arrays (i.e.) char my_dialog_resource[] = { .... };, and then use (e.g.) CreateDialogIndirect. You'll probably need to find (or write) a utility that converts from .RES files to .CPP files.
You can ship the LIB file with a resource script (.RC file) and corresponding header file. You then #include them as relevant. You'll need to reserve a range of resource IDs for the LIB to use, so that they don't collide with those of the main EXE or DLL. This is what MFC does when used as a static library. Or you can use string resource IDs (this doesn't work for STRINGTABLE resources).
Your static library can ship with a separate resource DLL.
I just went through this with the MS Visual Studio compiler. We were converting some legacy projects from DLLs into static libraries. Several of these DLLs had dialog or string resources embedded in them. I was able to compile the .RC scripts for these DLLs into our main application by including them in the main application's RC script file via the "TEXTINCLUDE" mechanism. I found it easiest to do this by editing the RC file directly, but Visual Studio provides a slightly more "wizardy" mechanism as well. The implementation is most likely different in other compilers.
To manipulate the main RC script directly:
.1. In the "2 TEXTINCLUDE" section, include the header file that defines the resource IDs for your library. The syntax is
2 TEXTINCLUDE
BEGIN
"#include ""my_first_lib_header.h""\r\n"
"#include ""my_second_lib_header.h""\0"
END
.2. In the "3 TEXTINCLUDE" section, include the RC script from your library.
3 TEXTINCLUDE
BEGIN
"#include ""my_first_library.rc""\r\n"
"#include ""my_second_library.rc""\0"
END
Steps 3 and 4 should happen automatically, but I found it was more reliable to just enter them myself, rather than depending on Microsoft's resource script compiler to take care of things.
.3. Add the header file with your libraries resource defines to the read only symbols list. This list is usually near the top of the file.
#define APSTUDIO_READONLY_SYMBOLS
#include "my_first_lib_header.h"
#include "my_second_lib_header.h"
#undef APSTUDIO_READONLY_SYMBOLS
.4. Include your library's RC script in the APSTUDIO_INVOKED section. This is usually at the bottom of the file.
#ifndef APSTUDIO_INVOKED
#include "my_first_library.rc"
#include "my_second_library.rc"
#endif
You can also do all of this automatically through the visual studio IDE, but I found it didn't always apply when I expected it to.
Open the "Resource View" window in Visual Studio.
Right-click on your main application's resource file and choose "Resource Includes..." from the context menu.
In the box labeled "Read-only symbol directives," add the include statements for the .h files that define the resource ID's for your libraries.
In the box labeled "Compile-time directives," add the include statements for your library's .rc script.
Click okay. You may also want to manually trigger the RC script compilation, to make sure it happens.
If your library's resource script references any files on disk (text files, icons files, etc.), you'll need to make sure that the main application project knows where to find them. You can either copy these files to somewhere your application can find them or you can add an additional include path in the compiler settings.
To add an additional include path:
Open up the properties dialog for your main application.
Select "Configuration Properties/Resources/General" from the left-hand navigation pane.
In the properties list, Enter any pertinent paths next to "Additional Include Directories."
As per Visual Studio 2010, the development tools from Microsoft apparently cannot properly handle compiled resource data inside static libraries at all.
To distribute a compiled resource file (a .res file), you have two choices:
Distribute the .res files separately, and instruct the client code to link against them;
Use cvtres to merge several .res files into a single object (.obj) file, and provide it separately.
Note that you can't lib in object files created with cvtres. If multiple object files are provided, lib complains as though as multiple .res files were given; if a single object file is provided, lib does not complain, but the linker simply ignores the embedded resource data in the lib file.
It might be the case that there is a way to force the linker to read and link the libbed in resource data (with some command-line option, section manipulation and so on), since the resource data is indeed available in the library (as dumpbin reveals). So far, I haven't found a solution, and, unless one is willing to hack the development tools, anything better than this simple solution is probably not worth the effort.
The only way to ship resource data in a static library (in this case, with a static library) is to distribute the resources separately and explicitly link them in the client code. Using cvtres can reduce the number of distributed resource files to one, if you have many of them.
I don't think so. Static library doesn't have it's own HINSTANCE. It's code is executed in the context of DLL or EXE which links it. That's why all the resources you'll try to load from the static library's code will be of that enclosing DLL/EXE.
I did that kind of resources reuse with a DLL though, as far as it has it's own address space, and you can call LoadResource with DLL's HINSTANCE.
The recommended way is to provide a dll with the resources together with your library.
When the following method is used, any resource (in this example, an icon) can be used as an integral part of a static library and such library can be used by any type of application, including a console one (which doesn't have any resource segment whatsoever).
Icon is converted to a static array of BYTE. bin2c can be used for that.
Data is converted into a HICON handle. Here is how I have done that:
HICON GetIcon()
{
DWORD dwTmp;
int offset;
HANDLE hFile;
HICON hIcon = NULL;
offset = LookupIconIdFromDirectoryEx(s_byIconData, TRUE, 0, 0, LR_DEFAULTCOLOR);
if (offset != 0)
{
hIcon = CreateIconFromResourceEx(s_byIconData + offset, 0, TRUE, 0x00030000, 0, 0, LR_DEFAULTCOLOR | LR_DEFAULTSIZE);
}
return hIcon;
}
GetIcon is used instead of LoadIcon.
Instead of calling:
m_hIcon = ::LoadIcon(hInstanceIcon, MAKEINTRESOURCE(pXMB->nIcon));
Then call
m_hIcon = GetIcon()