Back Midas Rome Roody Rootana
  Midas DAQ System, Page 99 of 157  Not logged in ELOG logo
ID Date Author Topic Subjectdown
  2515   12 May 2023 Konstantin OlchanskiInfoNew environment variable MIDAS_EXPNAME
> A new environment variable MIDAS_EXPNAME has been introduced [to be used together with 
MIDAS_DIR]

This is fixes an important buglet. If experiment uses MIDAS_DIR instead of exptab, at the time 
of connecting to ODB, we do not know the experiment name and use name "Default" to create ODB 
shared memory, instead of actual experiment name.

This creates an inconsistency, if some MIDAS programs in the same experiment use MIDAS_DIR while 
others use exptab (this would be unusual, but not impossible) they would connect to two 
different ODB shared memories, former using name "Default", latter using actual experiment name.

As an indication that something is not right, when stopping MIDAS programs, there is an error 
message about failure to delete shared ODB shared memory (because it was created using name 
"Default" and delete using the correct experiment name fails).

Also it can cause co-mingling between two different experiments, depending on the type of shared 
memory used by MIDAS (see $MIDAS_DIR/.SHM_TYPE.TXT):
POSIX - (usually not used) not affected (experiment name is not used)
POSIXv2 - (usually not used) affected (shm name is "$EXP_NAME_ODB")
POSIXv3 - used on MacOS - affected (shm name is "$UID_$EXP_NAME_ODB" so "$UID_Default_ODB" will 
collide)
POSIXv4 - used on Linux - not affected (shm name includes $MIDAS_DIR which is different for 
different experiments)

K.O.
  2542   20 Jun 2023 Stefan RittInfoNew environment variable MIDAS_EXPNAME
I just realized that we had already MIDAS_EXPT_NAME, and now people get confused with

MIDAS_EXPT_NAME
and
MIDAS_EXPNAME

In trying to fix this confusion, I changed the name of the second variable to MIDAS_EXPT_NAME as well, 
so we only have one variable now. If this causes any problems please report here.

Stefan
  2564   28 Jul 2023 Stefan RittInfoNew environment variable MIDAS_EXPNAME
Concerning naming of shared memories I went one step further due to some requirement of a local experiment. 
The experiment needs to change the experiment name shown on the web status page depending on the exact 
configuration, but we do not want to change the whole midas experiment each time.

So I simple removed the check that the experiment name coming from the environment and used for the shared 
memory gets checked against the experiment name in the ODB. The only connection there is that the ODB name 
gets set to the environment name is it does not exist or is empty, just to have some default value. So for 
most people nothing should change. If one changes however the name in the ODB (under /Experiment/Name), 
nothing will change internally, just the web display via mhttpd changes its title.

I hope this has no bad side-effects, so please have a look if you see any issue in your experiment.

Stefan
  668   02 Nov 2009 Exaos LeeSuggestionNew cmake files
Though ended with ".c", "lazylogger.c" has to be build with C++ compiler. I have 
to modify my CMakeLists.txt. 
Please see the attachment if you need it. It works with svn-r4616.
Attachment 1: cmake4midas.zip
  2921   12 Dec 2024 Stefan RittSuggestionNew alarm sound flag to be tested
We had the case in MEG that some alarms were actually just warnings, not very severe. This happens for example if we calibrate our detector 
once every other day and modify the hardware which actually triggers the alarm for about an hour or so.

The problem with this is now that the alarm sounds every few minutes, and people get annoyed during that hour. They turn down the volume 
of their speakers, or even disable the alarm sound. If the detector gets back into the default mode again, they might forget to re-enable the 
alarm, which causes some risk. 

Turning down the volume is also not good, since during that hour we could have a "real" alarm on which people have to react quickly in order 
not destroy the detector.

The art is now to configure the alarm system in a way that "normal" changes do not annoy people or cover up really severe alarms. After long 
discussions we came to following conclusion: We need a special class of alarm (let's call it 'warning') which does not annoy people. The 
warning should be visible on the screen, but not ring the alarm bell. 

While we have different alarm classes in midas, which let us customize the frequency of alarms and the screen colors, all alarms or warnings 
ring the alarm sound right now. This can be changed in the browser under "Config/Alarm sound" but that switch affects ALL alarms, which is 
not what we want.

The idea we came up with was to add a flag "Alarm sound" to the alarm classes. For the 'warning' we can then turn off the alarm sound, so 
only the banner is shown on top of the screen, and the spoken message is generated every 15 mins to remind people, but not to annoy them.

I added this "Alarm sound" flag in the branch feature/alarm_sound so everybody can test it. The downside is that all "Alarm/Classs/xxx" need 
to be modified to add this flag. While the new code will add this flag automatically (with a default value of 'true'), the size of the alarm class 
record changes by four bytes (one bool). Therefore, all running midas programs will complain about the changed size, until they get 
recompiled. 

Therefore, to test the new feature, you have to checkout the branch and  re-compile all midas programs you use, otherwise you will get errors 
like 

  Fixing ODB "/Alarms/Classes/Alarm" struct size mismatch (expected 352, odb size 348)

I will keep the branch for a few days for people to try it out and report any issue, and later merge it to develop.

Stefan
  2925   19 Dec 2024 Stefan RittSuggestionNew alarm count added
Another modification has been done to the alarm system. 

We have often cases where an alarm is triggered on some readout noise. Like an analog voltage just over the alarm threshold for a very short period of time, triggered sometimes from environmental 
electromagnetic effects like turning on the light. 

To mitigate this problem, an "alarm trigger count" has been implemented. Every alarm has now a variable "Trigger count required". If this value is zero (the default), the alarm system works as before. If this 
value is nowever set to a non-zero value N, the alarm limit has to be met on N consecutive periods in order to trigger the alarm. Each alarm has a "Check interval" which determines the period of the alarm 
checking. If one has for example:

Check interval = 10
Trigger count required = 3

then the alarm condition has to be met for 3 consecutive periods of 10 seconds each, or for 30 seconds in total. 

The modification has been merged into the develop branch, and people have to be aware that the alarm structures in the ODB changed. The current code tries to fix this automatically, but it is important 
that ALL MIDAS CLIENTS GET RE-COMPILED after the new code is applied. Otherwise we could have "new" clients expecting the new ODB structure, and some "old" clients expecting the old structure, 
then both types of clients would fight against each other and change the ODB structure every few seconds, leading to tons of error messages. So if you pull the current develop branch, make sure to re-
compile ALL midas clients.

/Stefan
  1906   12 May 2020 Stefan RittInfoNew ODB++ API
Since the beginning of the lockdown I have been working hard on a new object-oriented interface to the online database ODB. I have the code now in an initial state where it is ready for 
testing and commenting. The basic idea is that there is an object midas::odb, which represents a value or a sub-tree in the ODB. Reading, writing and watching is done through this 
object. To get started, the new API has to be included with

   #include <odbxx.hxx>

To create ODB values under a certain sub-directory, you can either create one key at a time like:

   midas::odb o;
   o.connect("/Test/Settings", true);   // this creates /Test/Settings
   o.set_auto_create(true);            // this turns on auto-creation
   o["Int32 Key"] = 1;                 // create all these keys with different types
   o["Double Key"] = 1.23;
   o["String Key"] = "Hello";

or you can create a whole sub-tree at once like:

  midas::odb o = {
    {"Int32 Key", 1},
    {"Double Key", 1.23},
    {"String Key", "Hello"},
    {"Subdir", {
      {"Another value", 1.2f}
    }
  };
  o.connect("/Test/Settings");

To read and write to the ODB, just read and write to the odb object

   int i = o["Int32 Key];
   o["Int32 Key"] = 42;
   std::cout << o << std::endl;

This works with basic types, strings, std::array and std::vector. Each read access to this object triggers an underlying read from the ODB, and each write access triggers a write to the 
ODB. To watch a value for change in the odb (the old db_watch() function), you can use now c++ lambdas like:

   o.watch([](midas::odb &o) {
      std::cout << "Value of key \"" + o.get_full_path() + "\" changed to " << o << std::endl;
   });

Attached is a full running example, which is now also part of the midas repository. I have tested most things, but would not yet use it in a production environment. Not 100% sure if there 
are any memory leaks. If someone could valgrind the test program, I would appreciate (currently does not work on my Mac).

Have fun!

Stefan

  
Attachment 1: odbxx_test.cxx
/********************************************************************\

  Name:         odbxx_test.cxx
  Created by:   Stefan Ritt

  Contents:     Test and Demo of Object oriented interface to ODB

\********************************************************************/

#include <string>
#include <iostream>
#include <array>
#include <functional>

#include "odbxx.hxx"
#include "midas.h"

/*------------------------------------------------------------------*/

int main() {

   cm_connect_experiment(NULL, NULL, "test", NULL);
   midas::odb::set_debug(true);

   // create ODB structure...
   midas::odb o = {
           {"Int32 Key", 42},
           {"Bool Key", true},
           {"Subdir", {
              {"Int32 key", 123 },
              {"Double Key", 1.2},
              {"Subsub", {
                 {"Float key", 1.2f},     // floats must be explicitly specified
                 {"String Key", "Hello"},
              }}
           }},
           {"Int Array", {1, 2, 3}},
           {"Double Array", {1.2, 2.3, 3.4}},
           {"String Array", {"Hello1", "Hello2", "Hello3"}},
           {"Large Array", std::array<int, 10>{} },   // array with explicit size
           {"Large String", std::string(63, '\0') },  // string with explicit size
   };

   // ...and push it to ODB. If keys are present in the
   // ODB, their value is kept. If not, the default values
   // from above are copied to the ODB
   o.connect("/Test/Settings", true);

   // alternatively, a structure can be created from an existing ODB subtree
   midas::odb o2("/Test/Settings/Subdir");
   std::cout << o2 << std::endl;

   // retrieve, set, and change ODB value
   int i = o["Int32 Key"];
   o["Int32 Key"] = i+1;
   o["Int32 Key"]++;
   o["Int32 Key"] *= 1.3;
   std::cout << "Should be 57: " << o["Int32 Key"] << std::endl;

   // test with bool
   o["Bool Key"] = !o["Bool Key"];

   // test with std::string
   std::string s = o["Subdir"]["Subsub"]["String Key"];
   s += " world!";
   o["Subdir"]["Subsub"]["String Key"] = s;

   // test with a vector
   std::vector<int> v = o["Int Array"];
   v[1] = 10;
   o["Int Array"] = v;        // assign vector to ODB object
   o["Int Array"][1] = 2;     // modify ODB object directly
   i = o["Int Array"][1];     // read from ODB object
   o["Int Array"].resize(5);  // resize array
   o["Int Array"]++;          // increment all values of array

   // test with a string vector
   std::vector<std::string> sv;
   sv = o["String Array"];
   sv[1] = "New String";
   o["String Array"] = sv;
   o["String Array"][2] = "Another String";

   // iterate over array
   int sum = 0;
   for (int e : o["Int Array"])
      sum += e;
   std::cout << "Sum should be 11: " << sum << std::endl;

   // creat key from other key
   midas::odb oi(o["Int32 Key"]);
   oi = 123;

   // test auto refresh
   std::cout << oi << std::endl;    // each read access reads value from ODB
   oi.set_auto_refresh_read(false); // turn off auto refresh
   std::cout << oi << std::endl;    // this does not read value from ODB
   oi.read();                       // this does manual read
   std::cout << oi << std::endl;

   midas::odb ox("/Test/Settings/OTF");
   ox.delete_key();

   // create ODB entries on-the-fly
   midas::odb ot;
   ot.connect("/Test/Settings/OTF", true);   // this forces /Test/OTF to be created if not already there
   ot.set_auto_create(true);        // this turns on auto-creation
   ot["Int32 Key"] = 1;             // create all these keys with different types
   ot["Double Key"] = 1.23;
   ot["String Key"] = "Hello";
   ot["Int Array"] = std::array<int, 10>{};
   ot["Subdir"]["Int32 Key"] = 42;
   ot["String Array"] = std::vector<std::string>{"S1", "S2", "S3"};
   std::cout << ot << std::endl;

   o.read();                        // re-read the underlying ODB tree which got changed by above OTF code
   std::cout << o.print() << std::endl;

   // iterate over sub-keys
   for (auto& oit : o)
      std::cout << oit.get_odb()->get_name() << std::endl;

   // print whole sub-tree
   std::cout << o.print() << std::endl;

   // dump whole subtree
   std::cout << o.dump() << std::endl;

   // delete test key from ODB
   o.delete_key();

   // watch ODB key for any change with lambda function
   midas::odb ow("/Experiment");
   ow.watch([](midas::odb &o) {
      std::cout << "Value of key \"" + o.get_full_path() + "\" changed to " << o << std::endl;
   });

   do {
      int status = cm_yield(100);
      if (status == SS_ABORT || status == RPC_SHUTDOWN)
         break;
   } while (!ss_kbhit());

   cm_disconnect_experiment();
   return 1;
}
  1913   20 May 2020 Konstantin OlchanskiInfoNew ODB++ API
>    midas::odb o;
>    o["foo"] = 1;

This is an excellent development.

ODB is a tree-structured database, JSON is a tree-structured data format,
and they seem to fit together like hand and glove. For programming
web pages, Javascript and JSON-style access to ODB seems to work really well.

And now with modern C++ we can have a similar API for working with ODB tree data,
as if it were Javascript JSON tree data.

Let's see how well it works in practice!

K.O.
  1914   20 May 2020 Stefan RittInfoNew ODB++ API
In meanwhile, there have been minor changes and improvements to the API:

Previously, we had:

>    midas::odb o;
>    o.connect("/Test/Settings", true);   // this creates /Test/Settings
>    o.set_auto_create(true);            // this turns on auto-creation
>    o["Int32 Key"] = 1;                 // create all these keys with different types
>    o["Double Key"] = 1.23;
>    o["String Key"] = "Hello";

Now, we only need:

      o.connect("/Test/Settings");
      o["Int32 Key"] = 1;                 // create all these keys with different types
      ...

no "true" needed any more. If the ODB tree does not exist, it gets created. Similarly, set_auto_create() can be dropped, it's on by default (thought this makes more sense). Also the iteration over subkeys has 
been changed slightly.

The full example attached has been updated accordingly. 

Best,
Stefan
Attachment 1: odbxx_test.cxx
/********************************************************************\

  Name:         odbxx_test.cxx
  Created by:   Stefan Ritt

  Contents:     Test and Demo of Object oriented interface to ODB

\********************************************************************/

#include <string>
#include <iostream>
#include <array>
#include <functional>

#include "midas.h"
#include "odbxx.hxx"

/*------------------------------------------------------------------*/

int main() {

   cm_connect_experiment(NULL, NULL, "test", NULL);
   midas::odb::set_debug(true);

   // create ODB structure...
   midas::odb o = {
      {"Int32 Key", 42},
      {"Bool Key", true},
      {"Subdir", {
         {"Int32 key", 123 },
         {"Double Key", 1.2},
         {"Subsub", {
            {"Float key", 1.2f},     // floats must be explicitly specified
            {"String Key", "Hello"},
         }}
      }},
      {"Int Array", {1, 2, 3}},
      {"Double Array", {1.2, 2.3, 3.4}},
      {"String Array", {"Hello1", "Hello2", "Hello3"}},
      {"Large Array", std::array<int, 10>{} },   // array with explicit size
      {"Large String", std::string(63, '\0') },  // string with explicit size
   };

   // ...and push it to ODB. If keys are present in the
   // ODB, their value is kept. If not, the default values
   // from above are copied to the ODB
   o.connect("/Test/Settings");

   // alternatively, a structure can be created from an existing ODB subtree
   midas::odb o2("/Test/Settings/Subdir");
   std::cout << o2 << std::endl;

   // set, retrieve, and change ODB value
   o["Int32 Key"] = 42;
   int i = o["Int32 Key"];
   o["Int32 Key"] = i+1;
   o["Int32 Key"]++;
   o["Int32 Key"] *= 1.3;
   std::cout << "Should be 57: " << o["Int32 Key"] << std::endl;

   // test with bool
   o["Bool Key"] = false;
   o["Bool Key"] = !o["Bool Key"];

   // test with std::string
   o["Subdir"]["Subsub"]["String Key"] = "Hello";
   std::string s = o["Subdir"]["Subsub"]["String Key"];
   s += " world!";
   o["Subdir"]["Subsub"]["String Key"] = s;

   // test with a vector
   std::vector<int> v = o["Int Array"]; // read vector
   std::fill(v.begin(), v.end(), 10);
   o["Int Array"] = v;        // assign vector to ODB array
   o["Int Array"][1] = 2;     // modify array element
   i = o["Int Array"][1];     // read from array element
   o["Int Array"].resize(5);  // resize array
   o["Int Array"]++;          // increment all values of array

   // test with a string vector
   std::vector<std::string> sv;
   sv = o["String Array"];
   sv[1] = "New String";
   o["String Array"] = sv;
   o["String Array"][2] = "Another String";

   // iterate over array
   int sum = 0;
   for (int e : o["Int Array"])
      sum += e;
   std::cout << "Sum should be 47: " << sum << std::endl;

   // creat key from other key
   midas::odb oi(o["Int32 Key"]);
   oi = 123;

   // test auto refresh
   std::cout << oi << std::endl;    // each read access reads value from ODB
   oi.set_auto_refresh_read(false); // turn off auto refresh
   std::cout << oi << std::endl;    // this does not read value from ODB
   oi.read();                       // this forces a manual read
   std::cout << oi << std::endl;

   // create ODB entries on-the-fly
   midas::odb ot;
   ot.connect("/Test/Settings/OTF");// this forces /Test/OTF to be created if not already there
   ot["Int32 Key"] = 1;             // create all these keys with different types
   ot["Double Key"] = 1.23;
   ot["String Key"] = "Hello";
   ot["Int Array"] = std::array<int, 10>{};
   ot["Subdir"]["Int32 Key"] = 42;
   ot["String Array"] = std::vector<std::string>{"S1", "S2", "S3"};
   std::cout << ot << std::endl;

   o.read();                        // re-read the underlying ODB tree which got changed by above OTF code
   std::cout << o.print() << std::endl;

   // iterate over sub-keys
   for (midas::odb& oit : o)
      std::cout << oit.get_name() << std::endl;

   // print whole sub-tree
   std::cout << o.print() << std::endl;

   // dump whole subtree
   std::cout << o.dump() << std::endl;

   // delete test key from ODB
   o.delete_key();

   // watch ODB key for any change with lambda function
   midas::odb ow("/Experiment");
   ow.watch([](midas::odb &o) {
      std::cout << "Value of key \"" + o.get_full_path() + "\" changed to " << o << std::endl;
   });

   do {
      int status = cm_yield(100);
      if (status == SS_ABORT || status == RPC_SHUTDOWN)
         break;
   } while (!ss_kbhit());

   cm_disconnect_experiment();
   return 1;
}
  1915   20 May 2020 Pintaudi GiorgioInfoNew ODB++ API
All this is very good news. I really wish this were available some months ago: it would have helped me immensely. The old C API was clunky at best.
I really like the idea and looking forward to using it (even if at the moment I do not have the need to) ...
  1916   20 May 2020 Konstantin OlchanskiInfoNew ODB++ API
> All this is very good news. I really wish this were available some months ago: it would have helped me immensely. The old C API was clunky at best.
> I really like the idea and looking forward to using it (even if at the moment I do not have the need to) ...

Yes, I have designed new C-style MIDAS ODB APIs twice now (VirtualOdb in ROOTANA and MVOdb in ROOTANA and MIDAS),
and I was never happy with the results. There is too many corner cases and odd behaviour. Let's see how
this C++ interface shakes out.

For use in analyzers, Stefan's C++ interface still need to be virtualized - right now it has only one implementation
with the MIDAS ODB backend. In analyzers, we need XML, JSON (and a NULL ODB) backends. The API looks
to be clean enough to add this, but I have not looked at the implementation yet. So "watch this space" as they say.

K.O.
  3031   30 Apr 2025 Stefan RittInfoNew ODB++ API
I had to change the ODBXX API: https://bitbucket.org/tmidas/midas/commits/273c4e434795453c0c6bceb46bac9a0d2d27db18

The old C API is case-insensitive, meaning db_find_key("name") returns a key "name" or "Name" or "NAME". We can discuss if this is good or bad, but that's how it is since 30 years.

I now realized the the ODBXX API keys is case sensitive, so a o["NAME"] does not return any key "name". Rather, it tries to create a new key which of course fails. I changed therefore
the ODBXX to become case-insensitive like the old C API.

Stefan
  3032   30 Apr 2025 Pavel MuratInfoNew ODB++ API
it is a very convenient interface! Does it support the ODB links in the path names ? -- thanks, regards, Pasha
  455   09 Mar 2008 Exaos LeeSuggestionNew Makefile for building MIDAS
I rewrote the Makefile for MIDAS in order to make it tidy. I tested it on my box
and it works here.
1. The full file is seperated to several parts
  a. initialized setup
  b. environment setup
  c. specify OS-specific flags
  d. processing environment for building flags
  e. targets
2. The file is less than 400 lines now. The original one is more than 500 lines.
3. The modified one is easy for debuging.

I tried to learn "autoconf" and "automake" in order to make building MIDAS more
compatible for various platforms. But I havn't enough time now. Hope somebody
can help it. The attached file is original named "Makefile.in" for using "autoconf".

:-)
Attachment 1: Makefile-by-EL
# initialized flags

#CC =
#FC = 
#LD =
CFLAGS   = -g -O3 -Wall -Wuninitialized -DINCLUDE_FTPLIB

###########################################################################
## Environments setup

## Prefix
ifndef PREFIX
PREFIX = /usr/local
endif

# User defined flags for compiler
USERFLAGS     =

# Do you need to compile the shared library? If so, set "1" here.
NEED_SHLIB    =

# If RPATH needed ...
NEED_RPATH    =

# If static ROOT libaries needed ...
NEED_LIBROOTA =

# If strlcpy.o needed ...
NEED_STRLCPY  = 1

# If zlib needed ...
NEED_ZLIB     =

# MIDAS max event size
MIDAS_MAX_EVENT_SIZE =

# OS specific programs included
SPECIFIC_OS_PRG      =

# ..? Why it is needed?
MIDAS_PREF_FLAGS     =

## installer

INSTALL  = $(shell which install)
ifndef INSTALL
INSTALL  = ./install.sh
else
INS_OPTS = -v -D
endif

# MXML dir
ifndef MXML_DIR
MXML_DIR = ../mxml
endif

# MySQL
MYSQL_CONFIG := $(shell which mysql_config 2> /dev/null)
ifdef MYSQL_CONFIG
MYSQLINCDIR := $(shell mysql_config --cflags | sed -e 's,^.*-I\([^ ]*\).*$$,\1,' -e s/\'//g)
NEED_MYSQL  := $(shell if test -e $(MYSQLINCDIR)/mysql.h ; then echo 1; fi) 
endif

###########################################################################
## Check OS Type for OS-specified flags

OSTYPE = $(shell uname | tr '[A-Z]' '[a-z]')

ifeq ($(OSTYPE), linux)
# > 2GB file support
CFLAGS  += -D_LARGEFILE64_SOURCE
CFLAGS  += -DOS_LINUX -fPIC -Wno-unused-function
LDFLAGS += -lutil -lpthread
NEED_ZLIB        =1
SPECIFIC_OS_PRG += mlxspeaker dio
endif

ifeq ($(OSTYPE), osf1)
CFLAGS  += -DOS_OSF1
FFLAGS  += -nofor_main -D 40000000 -T 20000000
LDFLAGS += -lc -lbsd
endif

ifeq ($(OSTYPE), ultrix)
CFLAGS  += -DOS_ULTRIX -DNO_PTY
endif

ifeq ($(OSTYPE), freebsd)
CFLAGS  += -DOS_FREEBSD
LDFLAGS += -lbsd -lcompat
endif

ifeq ($(OSTYPE), darwin)
CFLAGS  += -DOS_LINUX -DOS_DARWIN -DHAVE_STRLCPY -fPIC -Wno-unused-function
LDFLAGS += -lpthread
NEED_RANLIB      = 1
SPECIFIC_OS_PRG += mlxspeaker
endif

ifeq ($(OSTYPE), cygwin_nt-5.1)
OSTYPE = cygwin
endif

ifeq ($(OSTYPE), cygwin)
CFLAGS  += -DOS_LINUX -DOS_CYGWIN -Wno-unused-function
LDFLAGS += -lutil -lpthread
endif

ifeq ($(OSTYPE), solaris)
CFLAGS  += -DOS_SOLARIS
LDFLAGS += -lsocket -lnsl
endif

###########################################################################
## Processing environment for building flags

CFLAGS += $(MIDAS_PREF_FLAGS) $(USERFLAGS)

ifdef MIDAS_MAX_EVENT_SIZE
CFLAGS += -DMAX_EVENT_SIZE=$(MIDAS_MAX_EVENT_SIZE)
endif # MIDAS_MAX_EVENT_SIZE

ifdef NEED_MYSQL
CFLAGS  += -DHAVE_MYSQL $(shell $(MYSQL_CONFIG) --include)
LDFLAGS += $(shell $(MYSQL_CONFIG) --libs)
NEED_ZLIB =1
endif # NEED_MYSQL

ifdef ROOTSYS
ROOTLIBS    := $(shell $(ROOTSYS)/bin/root-config --libs)
ROOTCFLAGS  := $(shell $(ROOTSYS)/bin/root-config --cflags)

ifdef NEED_RPATH
ROOTLIBS   += -Wl,-rpath,$(ROOTSYS)/lib
endif

ifdef NEED_LIBROOTA
ROOTLIBS    := $(ROOTSYS)/lib/libRoot.a -lssl -ldl -lcrypt
endif

CFLAGS += $(ROOTCFLAGS)
endif # ROOTSYS

ifdef NEED_ZLIB
CFLAGS     += -DHAVE_ZLIB
LIBS       += -lz
endif # ZLIB

ifdef NEED_SHLIB
CFLAGS  += -shared -fPIC
endif # SHLIB

###########################################################################
## Processing building targets

## Directories needed

INC_DIR = include
SRC_DIR = src
UTL_DIR = utils
DRV_DIR = drivers
EXM_DIR = examples

## Driectories which will be created

OS_DIR  = $(OSTYPE)
LIB_DIR = $(OS_DIR)/lib
BIN_DIR = $(OS_DIR)/bin
DIRS    = $(OS_DIR)  $(LIB_DIR)  $(BIN_DIR)

CFLAGS += -I$(INC_DIR) -I$(DRV_DIR) -I$(MXML_DIR) -L$(LIB_DIR)

## Directories for install

INSTDIR_BIN = $(PREFIX)/bin
INSTDIR_INC = $(PREFIX)/include
INSTDIR_LIB = $(PREFIX)/lib
INSTDIR_DRV = $(PREFIX)/driver

## Utilities

PROGS = mserver  mhttpd  mlogger  odbedit  mtape   mhist    \
	mstat    mcnaf   mdump    mhdump    mchart  odbhist  \
	melog    webpaw  lazylogger   stripchart.tcl  \
	$(SPECIFIC_OS_PRG)

UTILS = $(shell for i in $(PROGS); do echo $(BIN_DIR)/$$i ; done)

## Analyzer objects

ANALYZER  = $(LIB_DIR)/mana.o
ifdef CERNLIB
ANALYZER += $(LIB_DIR)/hmana.o
endif
ifdef ROOTSYS
ANALYZER += $(LIB_DIR)/rmana.o
endif

## Objects for building $(LIBMIDAS_A) and $(LIBMIDAS_SO)

OBJS_LIB_NEED = midas.o  system.o  mrpc.o  odb.o  ybos.o  ftplib.o  history.o  alarm.o  elog.o

ifndef NEED_SHLIB
OBJS_LIB_NEED += cnaf_callback.o
endif

OBJS_LIB = $(shell for i in $(OBJS_LIB_NEED) ; do echo $(LIB_DIR)/$$i ; done)

## MXML OBJS

MXML_OBJS_NEED = mxml.o
ifdef NEED_STRLCPY
MXML_OBJS_NEED += strlcpy.o
endif

MXML_OBJS = $(shell for i in $(MXML_OBJS_NEED) ; do echo $(LIB_DIR)/$$i ; done)

## Objects for install

OBJS_INS_NEED = mfe.o fal.o
OBJS_INS = $(shell for i in $(OBJS_INS_NEED) ; do echo $(LIB_DIR)/$$i ; done)

## library

LIBMIDAS_A  = $(LIB_DIR)/libmidas.a
ifdef NEED_SHLIB
LIBMIDAS_SO  = $(LIB_DIR)/libmidas.so
LDFLAGS     += -shared -L$(LIB_DIR) -lmidas
endif

## Examples

EXAMPLES_NEED = consume produce rpc_test msgdump minife minirc odb_test
EXAMPLES = $(shell for i in $(EXAMPLES_NEED); do echo examples/$$i ; done)

## Includes

INCLUDES = $(wildcard $(INC_DIR)/*.h)

###########################################################################

CXXFLAGS  = $(CFLAGS)
ifdef ROOTSYS
CXXFLAGS += -DHAVE_ROOT
endif

all: check-mxml mkdirs $(LIBMIDAS_A) $(LIBMIDAS_SO) $(ANALYZER) $(OBJS_INS) utilities

.PHONY: clean

###########################################################################

## Library objects

$(LIB_DIR)/%.o: $(SRC_DIR)/%.c $(INCLUDES)
	$(CC) $(CFLAGS) -c -o $@ $<

## MXML_OBJS

$(LIB_DIR)/mxml.o: $(MXML_DIR)/mxml.c
	$(CC) $(CFLAGS) -c -o $@ $<

$(LIB_DIR)/strlcpy.o: $(MXML_DIR)/strlcpy.c
	$(CC) $(CFLAGS) -c -o $@ $<

## Frontend and backend framework

$(LIB_DIR)/fal.o: $(SRC_DIR)/fal.c $(INCLUDES)
	$(CXX) -Dextname -DMANA_LITE -c -o $@ $< $(CFLAGS)

$(LIB_DIR)/hmana.o: $(SRC_DIR)/mana.c $(INCLUDES)
	$(CC) -Dextname -DHAVE_HBOOK $(CFLAGS) -c -o $@ $<

$(LIB_DIR)/rmana.o: $(SRC_DIR)/mana.c $(INCLUDES)
	$(CXX) -DUSE_ROOT $(CXXFLAGS) -c -o $@ $<

## Utilities

$(BIN_DIR)/%: $(UTL_DIR)/%.c $(INCLUDES)
	$(CC) $(CFLAGS) -o $@ $< $(LIBMIDAS_A) $(LDFLAGS)

$(BIN_DIR)/mlogger: $(SRC_DIR)/mlogger.c $(LIBMIDAS_A)
	$(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) $(ROOTLIBS)
$(BIN_DIR)/mserver: $(SRC_DIR)/mserver.c $(INCLUDES)
$(BIN_DIR)/mhttpd:  $(SRC_DIR)/mhttpd.c  $(SRC_DIR)/mgd.c
$(BIN_DIR)/odbedit: $(SRC_DIR)/odbedit.c $(SRC_DIR)/cmdedit.c
$(BIN_DIR)/mcnaf:   $(UTL_DIR)/mcnaf.c   $(DRV_DIR)/camac/camacrpc.c
$(BIN_DIR)/mhdump:  $(UTL_DIR)/mhdump.cxx
	$(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(ROOTLIBS)
$(BIN_DIR)/lazylogger: $(SRC_DIR)/lazylogger.c
$(BIN_DIR)/stripchart.tcl: $(UTL_DIR)/stripchart.tcl
	@cp -f $< $(BIN_DIR)/$(shell basename $@)

###########################################################################

mkdirs:
	@for i in $(DIRS) ; do \
		echo "Making directory $$i ..." ; \
		mkdir -p $$i ; \
	done
... 108 more lines ...
  456   09 Mar 2008 Stefan RittSuggestionNew Makefile for building MIDAS
> I rewrote the Makefile for MIDAS in order to make it tidy. I tested it on my box
> and it works here.
> 1. The full file is seperated to several parts
>   a. initialized setup
>   b. environment setup
>   c. specify OS-specific flags
>   d. processing environment for building flags
>   e. targets
> 2. The file is less than 400 lines now. The original one is more than 500 lines.
> 3. The modified one is easy for debuging.
> 
> I tried to learn "autoconf" and "automake" in order to make building MIDAS more
> compatible for various platforms. But I havn't enough time now. Hope somebody
> can help it. The attached file is original named "Makefile.in" for using "autoconf".

I think it is a good idea to cleanup the Makefile. It grew over many years and certainly
had some inconsistencies. We did however not use "autoconf" since it is not of much use.
It is meant for systems where small differences between different Unix flavors are
covered by this system, but the midas source code is supposed not only to run on Unix,
but also on vxWorks and Windows. As you can imagine, the differences are much more
severe and a simple makefile generator cannot cover the details. Furthermore, under
Windows there is no such thing like autoconf. So all the work to make the source code
compile on all systems has been put into system.c using conditional compiling. So
putting another abstraction layer on this would maybe more complicate things than
simplify it. I will test your Makefile, and I also ask the guys at TRIUMF to do so. Once
we conclude that it works fine, we can replace the original Makefile from the distribution.
  458   10 Mar 2008 Stefan RittSuggestionNew Makefile for building MIDAS
> I rewrote the Makefile for MIDAS in order to make it tidy. I tested it on my box
> and it works here.
> 1. The full file is seperated to several parts
>   a. initialized setup
>   b. environment setup
>   c. specify OS-specific flags
>   d. processing environment for building flags
>   e. targets
> 2. The file is less than 400 lines now. The original one is more than 500 lines.
> 3. The modified one is easy for debuging.
> 
> I tried to learn "autoconf" and "automake" in order to make building MIDAS more
> compatible for various platforms. But I havn't enough time now. Hope somebody
> can help it. The attached file is original named "Makefile.in" for using "autoconf".

The Makefile is missing -lzip:

[ritt@pc5082 ~/midas]$ make -f Makefile-by-EL
Making directory linux ...
Making directory linux/lib ...
Making directory linux/bin ...
g++ -g -O3 -Wall -Wuninitialized -DINCLUDE_FTPLIB -D_LARGEFILE64_SOURCE -DOS_LINUX -fPIC
-Wno-unused-function   -DHAVE_ZLIB -Iinclude -Idrivers -I../mxml -Llinux/lib -o
linux/bin/mlogger src/mlogger.c linux/lib/libmidas.a -lutil -lpthread
/tmp/cceHnAKe.o(.text+0x83c): In function `midas_flush_buffer(LOG_CHN*)':
src/mlogger.c:984: undefined reference to `gzwrite'
/tmp/cceHnAKe.o(.text+0xb24): In function `midas_log_open(LOG_CHN*, int)':
src/mlogger.c:1132: undefined reference to `gzopen'
/tmp/cceHnAKe.o(.text+0xb46):src/mlogger.c:1140: undefined reference to `gzsetparams'
/tmp/cceHnAKe.o(.text+0xe2a): In function `midas_log_close(LOG_CHN*, int)':
src/mlogger.c:1208: undefined reference to `gzflush'
/tmp/cceHnAKe.o(.text+0xe40):src/mlogger.c:1210: undefined reference to `gzclose'
collect2: ld returned 1 exit status
make: *** [linux/bin/mlogger] Error 1
[ritt@pc5082 ~/midas]$
  459   10 Mar 2008 Konstantin OlchanskiSuggestionNew Makefile for building MIDAS
> I rewrote the Makefile for MIDAS in order to make it tidy.

Not that the current Makefile is too pretty (I have seen worse), but it works and it is fairly compact for a project of 
this complexity, it handles a large number of operating systems and build options very efficiently.

I think you found that out with your rewriting exercise - your version of the Makefile contains all the same code, 
just rearranged to suite your taste, with existing bugs preserved and new bugs added.

> I tested it on my box and it works here.

As they say, the devil is in the details. I notice some subtle changes in your Makefile that make me go "what?":

1) the command for building the midas shared library used to be "ld -shared", in your version, "-shared" is gone. 
But check with the GCC manual, today's recommended command is probably "gcc -shared".
2) mhdump is now linked with ROOT, but I wrote it recently enough to remember that it does not use ROOT
3) hand-crafted dependancies have been replaced with generic "almost every .o depends on every .h", which is 
incorrect. The "almost every .o" part bothers me.
4) "make clean" runs "rm -rf" - plain scary.
5) "$(shell ...)" is overused

I think by the end all these little details are sorted out and all the quirks are put back in, your Makefile will look no 
better than the current Makefile.

> 2. The file is less than 400 lines now. The original one is more than 500 lines.

It looks like your savings came from removing comments, removing hand-crafted dependancy lists and replacing 
fairly verbose "make install" targets (which we do not use anyway) with your own much simpler scripts.

All the juicy bits needed to actually build all the code appear to take about as much space as before.

Also the original mistake of recompiling programs when they only need relinking was not fixed. (For example, 
when libmidas is updated, to update mhttpd, the current Makefile needlessly recompiles mhttpd.c. Better use 
would be to compile mhttpd.c into mhttpd.o, then only a relink is needed).

> I tried to learn "autoconf" and "automake" in order to make building MIDAS more
> compatible for various platforms. But I havn't enough time now. Hope somebody
> can help it. The attached file is original named "Makefile.in" for using "autoconf".

Most experience with autoconf/automake is all negative. The promise was "never debug your Makefile ever 
again!", delivered was "debug the configure script instead!". In practice, with autoconf/automake, you try to run 
configure, kludge it until it stops crashing, then tweak the incomprehensible Makefiles it produces until the code 
compiles.

K.O.
  464   10 Mar 2008 Exaos LeeSuggestionNew Makefile for building MIDAS
> Most experience with autoconf/automake is all negative. The promise was "never debug your Makefile ever 
> again!", delivered was "debug the configure script instead!". In practice, with autoconf/automake, you try to run 
> configure, kludge it until it stops crashing, then tweak the incomprehensible Makefiles it produces until the code 
> compiles.
> 
> K.O.

I admit that the new one is fit to my flavor. For a common user, I think, a simple procedure of configure/make/install
is better than changing the Makefile manually because many users are lack of knowledges about Makefile. That's why 
I want to learn autotools. The configure script is generated automatically by "autoconf", so you needn't to debug it. 
For the developer, you need to debug the configure.ac/in files for generating the configure script. For a common user, 
he/she only needs to run it. In fact, some more complex projects like ROOT use AUTOTOOLS and they don't include 
the original files which are needed for generating the "configure" script.  I prefer the MIDAS project includes such a 
script to make the compiling simpler and easier instead of changing the Makefile manually. 
  465   10 Mar 2008 Exaos LeeSuggestionNew Makefile for building MIDAS
> The Makefile is missing -lzip:

Sorry, spelling error.
The "LIBS +=" should be replaced by "LDFLAGS +="
  470   12 Mar 2008 Konstantin OlchanskiSuggestionNew Makefile for building MIDAS
> > Most experience with autoconf/automake is all negative. The promise was "never debug your Makefile ever 
> > again!", delivered was "debug the configure script instead!". 
> 
> I admit that the new one is fit to my flavor. For a common user, I think, a simple procedure of configure/make/install
> is better than changing the Makefile manually because many users are lack of knowledges about Makefile. That's why 
> I want to learn autotools.

The reality is that you will never deliver a Makefile/Configure script that works for everybody in every case - users will always have a need to tweak the build 
process to suit their needs. In this situation, "Makefile" is a much better language and "make" is a much better tool for users to deal with - much simpler, better 
documented and better understood compared to autotools (*nobody* understands autotools; also compare the size of the midas Makefile with the size of a 
typical configure script).

Anyhow, we will be cross-compiling midas to run on a PowerPC processor inside a Virtex4 FPGA. Go handle that with configure scripts.

K.O.
ELOG V3.1.4-2e1708b5