How to get the object file in a static library with scons - static-libraries

I am using scons to build my project. Now I got a problem.
I use
env.StaticLibrary('a', [a1.o, a2.o])
to get a static library "liba.a".
Now I pass "liba.a" to another part of my project, in the part, I will generate another static library named "libb.a", and this will merge "liba.a" with some other object files.
The code like this:
env.StaticLibrary('b', ['liba.a', 'b1.o', 'b2.o'] )
In this question
Linking static libraries, that share another static library we know that we can not simply merge a static library into another static library, Because this may result in some symbol problems.
Now I want to solve this problem in this way:
First get the object file of 'liba.a'. Then merge this object files with new object files to generate the final 'libb.a'.
But I found I can not find a method or function to get the object files in a static library with scons.
Can anyone help me ?

Sounds like you just want to use the same object files for 2 different libraries.
You could do something like this:
env = Environment()
env.StaticLibrary('a', ['a1.o', 'a2.o'])
env.StaticLibrary('b', ['b1.o', 'b2.o', 'a1.o', 'a2.o'])
Additionally, instead of dealing with the Object files, you could directly specify the source files. In this case, SCons will only compile the source files once, as needed.
env.StaticLibrary('a', ['a1.c', 'a2.c'])
env.StaticLibrary('b', ['b1.c', 'b2.c', 'a1.c', 'a2.c'])
Also, remember that each SCons builder returns a list of targets (each being a SCons Node). The list may have one or several entries. So, for example, the following target variable will contain the library target, and all of the objects built:
target = env.StaticLibrary('a', ['a1.c', 'a2.c'])
for t in target: print str(t)

Related

using qt with adtf. Generation of moc file during build time?

I am trying to use qt with adtf 3.3 .
From the documentation of adtf (https://support.digitalwerk.net/adtf/v3/adtf_html/page_external_dependencies.html) and example from adtf using qt(https://support.digitalwerk.net/adtf/v3/adtf_html/page_demo_qt_video_display_code.html).
Brief intro about what i am trying to do.
I have created one ui file using QtDesigner and then i generated manually header file using uic compiler then also generated moc file since i have signal and slots functionality i also need moc file to call metaobjects.
So Now i would like to do is instead of generating manually header file using uic and moc file i wanted to generate moc file during build time using
set(CMAKE_AUTOMOC_ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)
the reason why i am doing like this if i change some functionality or added some signal and slots then i need to generate separatley and add in the sources file.
So basically my header file generated by uic contains info about objects used in qt form. Basically it translates xml file type which contains information about ui to header file using uic compiler.
#include <QtCore/QVariant>
#include <QtWidgets/QAction>
#include <QtWidgets/QApplication>
#include <QtWidgets/QButtonGroup>
#include <QtWidgets/QCheckBox>
#include <QtWidgets/QGroupBox>
#include <QtWidgets/QHeaderView>
#include <QtWidgets/QPlainTextEdit>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QTableWidget>
#include <QtWidgets/QWidget>
#include <QLineEdit>
QT_BEGIN_NAMESPACE
class Ui_Form
{
public:
QGroupBox *groupBox_dummy;
void setupUi(QWidget *Form)
{
if (Form->objectName().isEmpty())
Form->setObjectName(QStringLiteral("Form"));
//Form->resize(960, 480);
Form->setFixedSize(960, 480);
/*Contains several qobjects removed intentionally as it makes post so long*/
retranslateUi(Form);
QMetaObject::connectSlotsByName(Form);
} // setupUi
void retranslateUi(QWidget *Form)
{
} // retranslateUi
};
namespace Ui {
class Form: public Ui_Form {};
} // namespace Ui
QT_END_NAMESPACE
and then i have a moc file generated my moc compiler they are always generated for all QObject classes. They are absolutely required for meta stuff to work, so things like: signals for example.
My CMAKELists look like
set (CMAKE_CXX_STANDARD 11)
include(FetchContent)
find_package(ADTF REQUIRED HINTS ${ADTF_DIR} COMPONENTS filtersdk ui)
adtf_use_qt(Widgets)
set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--export-all-symbols")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
find_package(Eigen3 CONFIG REQUIRED HINTS ${CMAKE_SOURCE_DIR}/libs/eigen/share/eigen3/cmake)
set(OpenCV_STATIC ON)
find_package(OpenCV CONFIG REQUIRED HINTS ${CMAKE_SOURCE_DIR}/libs/opencv)
# include directories
include_directories(inc)
include_directories(${CMAKE_BINARY_DIR})
include_directories(${OpenCV_INCLUDE_DIRS})
include_directories(${EIGEN3_INCLUDE_DIR})
# specify target
set(TARGET_NAME dummy)
set (TARGET_SOURCES
inc/uic_dummy.h->file generated by uic compiler. this code snipper is shown above
inc/dummy.h -> this basically contains several methods like createview and severalt hings and also slots (for qt functionality)
inc/stdafx.h -> contains all includes in this file
src/dummy.cpp->definitions of all the functions mentioned in dummy.h
src/moc_dummy.cpp-> moc file everytime i need to keep in the sources list. However i want to generate it in build time instead of saying like this uisng CMAKE_AUTOMOC ON
)
adtf_add_filter(${TARGET_NAME} ${TARGET_SOURCES})
target_link_libraries(${TARGET_NAME} PRIVATE Qt5::Widgets ${OpenCV_LIBS} adtf::ui)
adtf_disable_qt_warnings(${TARGET_NAME})
adtf_install_target(${TARGET_NAME} ${CMAKE_INSTALL_PREFIX}/dummy/dummy)
adtf_create_plugindescription(
/*removed intentionall as it is not the area of the concern in this scenario*/
)
So my question is can i generate moc file in build time?
Since I am using adtf_use_qt(widgets) and in cmake gui i point out qt_dir then everything works fine. However i need to keep moc file in the sources.
Normally when i use qt withouf adtf i basicall use find_package(qt) and also use
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE AUTORCC ON)
Then i will only keep my ui file in the sources and then it generates
everyhting forme. Ideally i would like to know if i can do the same for adtf.
Please excuse me if my question is not clear.If you need any more info please ask i will try to elaborate in a much better way than this. Thanks
are you still having trouble creating your moc files?
Maybe you only have to add your xxx.ui file to the filter sources.
The ui_xxx.h could be included within your source files.
For example:
set(PLUGIN_TARGETNAME your_filter)
adtf_add_filter(${PLUGIN_TARGETNAME}
${PLUGIN_TARGETNAME}.h
${PLUGIN_TARGETNAME}.cpp
${PLUGIN_TARGETNAME}.ui
)
target_link_libraries(${PLUGIN_TARGETNAME} PRIVATE
adtf::systemsdk
adtf::filtersdk
adtf::ui)
set_target_properties(${PLUGIN_TARGETNAME} PROPERTIES FOLDER src)
adtf_create_plugindescription(
TARGET ${PLUGIN_TARGETNAME}
PLUGIN_SUBDIR "bin")
set_target_properties(${PLUGIN_TARGETNAME}
PROPERTIES AUTOMOC ON AUTOUIC ON AUTOGEN_TARGET_DEPENDS ${PLUGIN_TARGETNAME}.ui)

intersphinx link creation issues for local files across multiple projects

I have a few different Sphinx projects that I would like to refer to each other locally (no web server). I have separate code + build directories setup for the projects and was trying out intersphinx to solve this requirement.
My questions are:
Is there a better way of referring to two or more local projects within Sphinx?
Is there a way to strip out the second build in the path?
In my configuration file I have:
intersphinx_mapping = {
'doc1': ('../build/doc1',None)
}
so I get no issues in doing a make HTML, however when I look at the reference I've created with :ref:'doc1 info <doc1:label1>' I have in the HTML document:
file:///<root path>/build/**build**/doc1/html/doc.html#label1
So the issue is I get two "build" directory listings - it should of been:
file:///<root path>/build/doc1/html/doc.html#label1.
If I manually do this, it correctly pulls in the document.
I've also tried replacing None with '../build/doc1'. If I drop the build from the mapping I do get an error in finding the objects.inv file for doc1.
I do not want to use absolute path since the end user getting this documentation may see it in another location and I want this to be cross platform...
My directory tree is essentially as follows:
Makefile
build/doc1/html
build/doc2/html
doc1
doc2
As a background, I'm trying this under Cygwin with Sphinx 1.7.5... I haven't tried Linux yet to see if I get the same behavior...
You can set a different path for your target and for your inventory.
Maybe you can try something like:
intersphinx_mapping = {
'doc1': ('../doc1', '../build/doc1/objects.inv')
}
If you want to keep the None, it is also possible to have both:
intersphinx_mapping = {
'doc1': ('../doc1', (None, '../build/doc1/objects.inv'))
}

How do you customize the identifier used by MinispadeFilter in rake-pipeline

Per this question: Setting up rake-pipeline for use with handlebars alongside Google App Engine
I'm using a MinispadeFilter as my dependency management system via rake-pipeline.
The weird thing I'm seeing is the coffeescript and handlebars files have their minispade identifier set to a tmp directory (I'm assuming, where the work is being done). screencast.com/t/wIXmREcreW
Is there a way to set that to a root path such that it is normalized? Likewise my js files, while not pointing to a tmp path, are pointing to the original assets path instead of the public path. I know its just an identifier, but should I expect them to reference the public path? screencast.com/t/k9kZNcPo
The MinispadeFilter is pretty dumb about generating module identifiers by default. It just names them after the path of the input files. You're seeing the tmp dirs in there from handlebars and coffeescript because the minispade filter is getting the module id from the place where the pipeline turns them into javascript.
The filter takes a :module_id_generator option which allows you to customize the generation of module ids. If you're not familiar with Ruby, this may be a little heavy for you, so bear with me. The module_id_generator option takes a Ruby proc, which is like an anonymous function in JS. The filter then takes this proc that you pass in and executes it for each input file, passing your proc a FileWrapper object representing the input file, and your proc should return a string that will be used as the module id for that file.
Here's a match block from one of my projects:
match "**/*.js" do
minispade :module_id_generator => proc { |input| input.path.sub(/lib\//, 'timelog/').sub(/\.js$/, '') }
concat "js/app.js"
end
The :module_id_generator is a proc which takes a FileWrapper named input and turns it into the module id I want. The input file's path is available as the path method on input. In this case, my JS files are in a lib/ directory, so I use Ruby's sub method to replace the beginning lib/ part of the path with timelog (the name of the project) then again to remove the .js extension. So a js file named lib/models.js would get a module id of timelog/models.

How to find all dependency (class files) for a C# class file

I have a number of test classes in C# (NUnit Test scripts, compiling on Mono).
Instead of compiling all unit tests into one big assembly, as usual, I'd like to compile the individual class files into separate assemblies. To do so, I'd like to do a dependency analysis, so I can generate the separate assemblies automatically.
What I'm looking for is similar to class dependency analyser which exists for Java
Have a look at Mono Cecil.
This library has the capability to 'reflect' (not a very good name for it) on the actual assembly image to do analysis. This assumes that you would be willing to compile down to a 'big' assembly in order to run the dependency analysis using Mono.Cecil.
Edit In fact, you might simply use Cecil to copy the 'big' assembly while filtering out parts of it. That way, you'll not have much of the complexity of compiling the separate assemblies; Look at CecilRoundtrip sample for an example of how to roundtrip (read -> manipulate -> save) assemblies in Cecil.
I have previously published quite extensive examples of how to use Mono Cecil for 'advanced' searches (static call tree search, in essence):
Get types used inside a C# method body
Look if a method is called inside a method using reflection
The absolute bare minimum that would be most useful to you would probably be:
var types = assemblies
.SelectMany(assembly => assembly.MainModule.Types.Cast<TypeDefinition>());
var dependencies = types.ToDictionary(
key => key,
typedef => new HashSet<string>(typedef.Methods.Cast<MethodDefinition>()
.Where(method => null != method.Body) // ignore abstracts and generics
.SelectMany(method => method.Body.Instructions.Cast<Instruction>())
.Select(instr => instr.Operand)
.OfType<TypeReference>().Distinct()
// .Where(type => !type.Namespace.StartsWith("System"))
.Select(type => type.Name)));
foreach (var entry in dependencies)
{
Console.WriteLine("{0}\t{1}", entry.Key.Name, string.Join(", ", entry.Value.ToArray()));
}
Note the commented line optionally filters out things from the framework (System.String, System.Char etc.).
This will list required types per declared type. To list types used, simply tag on the lookup to assembly name:
.Select(type => type.Module.Assembly.Name.Name)));
Sample output of the first kind (types required):
SegmentSoortKenmerk SegmentSoortKenmerk
OperatorValue
Koppelpad Koppelpad, CodeLeidendVolgend
RedenWaarschuwing
RelExceptions
GecontroleerdDocument GecontroleerdDocument, GecontroleerdDocument[]
OwiExtraKenmerk OwiExtraKenmerk, Gegeven, BackofficeRelatie
Entiteit Entiteit, SleutelSysteemObject[], EniteitType
Similar query but using the assembly name lookup:
SegmentSoortKenmerk Lspo.Business
OperatorValue
Koppelpad Lspo.Business
RedenWaarschuwing
RelExceptions
GecontroleerdDocument Lspo.Business
OwiExtraKenmerk Lspo.Business
Entiteit Lspo.Business
Assuming you want to run nunit tests on mono, that should work just fine, ( I am happily using NUnit 2.5 and 2.4 on mono 2.10.6 ).
One common mistake is only copying or keeping track of the .dll file containing the tests. Like any program, the test has dependencies, in your case, they will at least be nunit.framework.dll plus the class/assembly you wish to test ( and any of it's dependencies )
If all you want however is to find the assemblies a given dll references (things it needs to run) you can do this quite easily:
using System.Reflection;
void PrintRefs( string dllfile ){
var asm = Assembly.ReflectionOnlyLoad ( dllfile );
foreach ( var aname in asm.GetReferencedAssemblies() ){
Console.WriteLine( aname.Name );
}
}
Beware, this will only find the names of assemblies the program or library was compiled with, not any that it might dynamically load at runtime.

Including DirectShow library into Qt for video thumbnail

I'm trying to implement http://msdn.microsoft.com/en-us/library/dd377634%28v=VS.85%29.aspx on Qt, to generate a poster frame/thumbnail for video files.
I have installed both Windows Vista and Windows 7 SDK. I put:
#include "qedit.h"
in my code (noting there is also one in C:\Qt\2010.04\mingw\include), I add:
win32:INCLUDEPATH += $$quote(C:/WindowsSDK/v6.0/Include)
to my *.pro file. I compile and get " error: sal.h: No such file or directory". Finding this in VC++ I add
win32:INCLUDEPATH += $$quote(C:/Program Files/Microsoft Visual Studio 10.0/VC/include)
And now have 1400 compile errors. So, I abandon that and just add:
win32:LIBS += C:/WindowsSDK/v7.1/Lib/strmiids.lib
to my *.pro file and try to run (without including any headers):
IMediaDet mediadet;
But then I get "error: IMediaDet: No such file or directory".
#include "qedit.h"
gives me the same error (it looks like it's pointing to the Qt version) and
#include "C:/WindowsSDK/v6.0/Include/qedit.h"
goes back to generating 1000's of compile errors.
Sigh, so much trouble for what should be 10 lines of code...
Thanks for your comments and help
Since you say you are "a C++/Qt newbie" then I suspect that the real issue may be that you are attempting to load the library yourself rather than simply linking your application to it?
To link an external library into your application with Qt all you need to do is modify the appropriate .pro file. For example if the library is called libfoo.dll you just add
LIBS += -L/path/to/lib -lfoo
You can find more information about this in the relevant section of the qmake manual. Note that qmake commonly employs Unix-like notation and transparently does the right thing on Windows.
Having done this you can include the library's headers and use whatever classes and functions it provides. Note that you can also modify the project file to append an include path to help pick up the headers eg.
INCLUDEPATH += /path/to/headers
Again, more information in the relevant section of the qmake manual.
Note that both these project variables work with relative paths and will happily work with .. to mean "go up a directory" on all platforms.
Note that qedit.h requires dxtrans.h, which is part of DirectX9 SDK.
You can find dxtrans.h in DirectX SDK from August 2006. Note that dxtrans.h is removed from newer DirectX SDKs.
Do you have access to the source of the external library? The following assumes that you do.
What I do when I need to extract a class from a library with only functions resolved, is to use a factory function in the library.
// Library.h
class SomeClass {
public:
SomeClass(std::string name);
// ... class declaration goes here
};
In the cpp file, I use a proxy function outside the extern "C" when my constructor requires C++ parameters (e.g. types such as std::string), which I pass as a pointer to prevent the compiler from messing up the signature between C and C++. You can avoid the extra step if your constructor doesn't require parameters, and call new SomeClass() directly from the exported function.
// Library.cpp
#include "Library.h"
SomeClass::SomeClass(std::string name)
{
// implementation details
}
// Proxy function to handle C++ types
SomeClass *ImplCreateClass(std::string* name) { return new SomeClass(*name); }
extern "C"
{
// Notice the pass-by-pointer for C++ types
SomeClass *CreateClass(std::string* name) { return ImplCreateClass(name); }
}
Then, in the application that uses the library :
// Application.cpp
#include "Library.h"
typedef SomeClass* (*FactoryFunction)(std::string*);
// ...
QLibrary library(QString("MyLibrary"));
FactoryFunction factory = reinterpret_cast(library.resolve("CreateClass"));
std::string name("foobar");
SomeClass *myInstance = factory(&name);
You now hold an instance of the class declared in the library.

Resources